﻿
// MFCApplication1Dlg.cpp: 实现文件
//

#include "pch.h"

#include "MFCApplication1Dlg.h"

#include "MFCApplication1.h"
#include "afxdialogex.h"
#include "framework.h"

#include <chrono>
#include <format>
#include <ranges>

#ifdef _DEBUG
#    define new DEBUG_NEW
#endif

#define IDC_MB 0
#define WM_LOADEDDATA (WM_USER + 1)
// CMFCApplication1Dlg 对话框

CMFCApplication1Dlg::CMFCApplication1Dlg(std::wstring url, CWnd* pParent /*=nullptr*/)
	: CDialog(IDD_MFCAPPLICATION1_DIALOG, pParent)
	, m_url(std::move(url))
	, m_lastInputData{
		20,
		10000,
		5,
		0,
		0,
		true,
	}
	, m_formData(m_lastInputData)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CMFCApplication1Dlg::DoDataExchange(CDataExchange *pDX)
{
    CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CMFCApplication1Dlg, CDialog)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_SIZE()
ON_MESSAGE(WM_LOADEDDATA, &CMFCApplication1Dlg::OnLoadedData)
ON_WM_DESTROY()
END_MESSAGE_MAP()

BEGIN_EASYSIZE_MAP(CMFCApplication1Dlg)
EASYSIZE(IDC_MB, ES_BORDER, ES_BORDER, ES_BORDER, ES_BORDER, 0)
END_EASYSIZE_MAP

// CMFCApplication1Dlg 消息处理程序

BOOL CMFCApplication1Dlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // 设置此对话框的图标。  当应用程序主窗口不是对话框时，框架将自动
    //  执行此操作
    SetIcon(m_hIcon, TRUE);  // 设置大图标
    SetIcon(m_hIcon, FALSE); // 设置小图标

    LoadURL();
    BindFunctions();
    INIT_EASYSIZE;

    return TRUE; // 除非将焦点设置到控件，否则返回 TRUE
}

void CMFCApplication1Dlg::LoadURL()
{
    CRect rcLayout;
    GetClientRect(rcLayout);
    m_mbWin.Create(rcLayout, this);
    wkeLoadURLW(m_mbWin, m_url.c_str());
}

// 如果向对话框添加最小化按钮，则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序，
//  这将由框架自动完成。

void CMFCApplication1Dlg::OnPaint()
{
    if (IsIconic())
    {
        CPaintDC dc(this); // 用于绘制的设备上下文

        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

        // 使图标在工作区矩形中居中
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // 绘制图标
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialog::OnPaint();
    }
}

// 当用户拖动最小化窗口时系统调用此函数取得光标
// 显示。
HCURSOR CMFCApplication1Dlg::OnQueryDragIcon()
{
    return static_cast<HCURSOR>(m_hIcon);
}

void CMFCApplication1Dlg::OnSize(UINT nType, int cx, int cy)
{
    CDialog::OnSize(nType, cx, cy);

    UPDATE_EASYSIZE;
}

void CMFCApplication1Dlg::BindFunctions()
{
    wkeJsBindFunction("initData", jsInitData, this, 0);
    wkeJsBindFunction("onOk", jsOnOk, this, 1);
    wkeJsBindFunction("onCancel", jsOnCancel, this, 0);
    wkeJsBindFunction("loadData", jsLoadData, this, 0);
}

jsValue WKE_CALL_TYPE CMFCApplication1Dlg::jsInitData(jsExecState es, void *vptr)
{
    auto *pDlg = static_cast<CMFCApplication1Dlg *>(vptr);
    const std::string json = xpack::json::encode(pDlg->m_lastInputData);
    return jsString(es, json.c_str());
}

jsValue WKE_CALL_TYPE CMFCApplication1Dlg::jsOnOk(jsExecState es, void *vptr)
{
    auto *pDlg = static_cast<CMFCApplication1Dlg *>(vptr);
    if (jsArgCount(es) != 1)
        return jsUndefined();
    auto value = jsArg(es, 0);
    auto type = jsTypeOf(value);
    if (!jsIsString(value))
        return jsUndefined();
    const auto *szTitle = jsToTempString(es, value);
    xpack::json::decode(szTitle, pDlg->m_formData);
    pDlg->OnOK();
    return jsUndefined();
}

jsValue WKE_CALL_TYPE CMFCApplication1Dlg::jsOnCancel(jsExecState es, void *vptr)
{
    auto *pDlg = static_cast<CMFCApplication1Dlg *>(vptr);
    pDlg->OnCancel();
    return jsUndefined();
}

jsValue WKE_CALL_TYPE CMFCApplication1Dlg::jsLoadData(jsExecState es, void *vptr)
{
    auto *pDlg = static_cast<CMFCApplication1Dlg *>(vptr);
    pDlg->LoadData();
    return jsUndefined();
}

void CMFCApplication1Dlg::LoadData()
{
    m_loadData = std::thread(
        [this]() -> void
        {
            for (auto i : std::views::iota(0))
            {
                using namespace std::chrono_literals;
                std::this_thread::sleep_for(1ms);
                if (i == 500)
                    break;
            }
            auto p = reinterpret_cast<LPARAM>(new double(10000));
            PostMessage(WM_LOADEDDATA, 0, p);
        });
}

afx_msg LRESULT CMFCApplication1Dlg::OnLoadedData(WPARAM wParam, LPARAM lParam)
{
    std::unique_ptr<double> p(reinterpret_cast<double *>(lParam));
    const double v = *p;
    auto js = std::format("window.loadedData({});", v);
    wkeRunJS(m_mbWin, js.c_str());

    return 0;
}

void CMFCApplication1Dlg::OnDestroy()
{
    CDialog::OnDestroy();

    if (m_loadData.joinable())
        m_loadData.join();
}
